package com.ffzx.commerce.framework.controller;

import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.bind.ValidationException;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.alibaba.fastjson.JSON;
import com.ffzx.commerce.framework.annotation.ServiceResult;
import com.ffzx.commerce.framework.constant.Constant;
import com.ffzx.commerce.framework.page.Page;
import com.ffzx.commerce.framework.utils.DateEditor;
import com.ffzx.commerce.framework.utils.StringUtil;

/**
 * controller基础类
 * 
 * @author liujunjun
 * @date 2016年1月13日 上午10:59:45
 * @version 1.0
 */
public class BaseController {

	private final static Logger logger = LoggerFactory.getLogger(BaseController.class);
	private static ThreadLocal<Map<String,Object>> outPutMsg = new ThreadLocal<Map<String,Object>>();
	
	public static final int DEFAULT_PAGE_SIZE = 15;

	/**
	 * 获取request
	 * 
	 * @return
	 */
	protected HttpServletRequest getRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}

	/**
	 * 获取session
	 * 
	 * @return
	 */
	protected HttpSession getSession() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
	}

	/**
	 * 设置分页信息
	 * 
	 * @param pageNow
	 * @param pageSize
	 * @param orderby
	 * @return
	 */
	public Page getSimplePage(String pageNow, String pageSize) {
		int pageNo = 0;
		int pSize = DEFAULT_PAGE_SIZE;
		if (pageNow != null && !"".equals(pageNow)) {
			pageNo = Integer.parseInt(pageNow);
		}
		if (pageSize != null && !"".equals(pageSize)) {
			pSize = Integer.parseInt(pageSize);
		}
		return new Page(pageNo, pSize);
	}
	
	/**
	 * 设置分页信息
	 * 
	 * @param pageNow
	 * @param pageSize
	 * @param orderby
	 * @return
	 */
	public Page getPageObj() {
		int pageIndex = 0;
		int pageSize = 0;
		
		HttpServletRequest request = getRequest();
		String indexStr = request.getParameter("pageIndex");
		String sizeStr = request.getParameter("pageSize");
		try {
			if (StringUtil.isNum(indexStr)){
				pageIndex = Integer.parseInt(indexStr);
			}
			if (StringUtil.isNum(sizeStr)){
				pageSize = Integer.parseInt(sizeStr);
			}
		} catch (Exception e) {
		}
		
		return new Page(pageIndex, pageSize);
	}

	/**
	 * 获取页面传递的某一个参数值
	 */
	public String getPara(String key) {
		return getRequest().getParameter(key);
	}

	/**
	 * 获取页面传递的某一个数组值
	 */
	public String[] getParaValues(String key) {
		return getRequest().getParameterValues(key);
	}

	/**
	 * 返回josn
	 * 
	 * @param object
	 * @return
	 */
	public String getJsonByObject(Object object) {
		return JSON.toJSONStringWithDateFormat(object, Constant.DEFAULT_DATA_FORMAT);
	}

	/**
	 * responseWrite "application/json;charset=utf-8"
	 * 
	 * @param response
	 * @param returns
	 */
	public void responseWrite(HttpServletResponse response, String returns) {
		response.setContentType(Constant.RESPONSE_CONTENT_TYPE);
		try {
			response.getWriter().write(returns);
			response.getWriter().flush();
			response.getWriter().close();
            getOutputMsg().clear();
		} catch (IOException e) {
			logger.error("BaseController.responseWrite()方法出错:",  e);
		}
	}
	
	/**
	 * 线程绑定，其内容会在outPrint方法调用后清空
	 * @return the outputMsg
	 */
	public Map<String,Object> getOutputMsg() {
		Map<String,Object> output = outPutMsg.get();
		if(output==null){
			output = new HashMap<String, Object>();
			outPutMsg.set(output);
		}
		return output;
	}
	
	/**获取所有参数*/
	@SuppressWarnings("rawtypes")
	protected Map<String,String> getParamMap(){
		Map<String,String> parameters = new HashMap<String, String>();
		Map map = getRequest().getParameterMap(); 
		Set keys = map.keySet();
		for(Object key : keys){
			parameters.put(key.toString(), getRequest().getParameter(key.toString()));
		}
		return parameters;
	}
	/**
	 * 将参数封装成Map<String,Object>空字符串转为null 
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	protected Map<String,Object> getParaMap(){
		Map<String,Object> parameters = new HashMap<String, Object>();
		Map map = getRequest().getParameterMap();
		Set keys = map.keySet();
		for(Object key : keys){
			Object o=getRequest().getParameter(key.toString());
			if(o instanceof String ){
				if("".equals(o)){
					o=null;
				}
			}
			parameters.put(key.toString(), o);
		}
		return parameters;
	}
	/**获取指定参数*/
	public String getString(String name) {
		return getString(name, null);
	}

	public String getString(String name, String defaultValue) {
		String resultStr = getRequest().getParameter(name);
		if (resultStr == null || "".equals(resultStr)
				|| "null".equals(resultStr) || "undefined".equals(resultStr)) {
			return defaultValue;
		} else {
			return resultStr;
		}
	}
	
	public int getInt(String name) {
		return getInt(name, 0);
	}

	public int getInt(String name, int defaultValue) {
		String resultStr = getRequest().getParameter(name);
		if (resultStr != null) {
			try {
				return Integer.parseInt(resultStr);
			} catch (Exception e) {
				return defaultValue;
			}
		}
		return defaultValue;
	}

	public BigDecimal getBigDecimal(String name) {
		return getBigDecimal(name, null);
	}
	
	public BigDecimal getBigDecimal(String name, BigDecimal defaultValue) {
		String resultStr = getRequest().getParameter(name);
		if (resultStr != null) {
			try {
				return BigDecimal.valueOf(Double.parseDouble(resultStr));
			} catch (Exception e) {
				return defaultValue;
			}
		}
		return defaultValue;
	}

	/**
	 * 构造基本的返回结构体
	 * 
	 * @param actionName
	 * @return 基础返回结构体
	 */
	protected String buildResponse(ServiceResult serviceResult) {
		return this.getJsonByObject(responseMap(serviceResult.code() + "", serviceResult.msg()));
	}

	/**
	 * 将错误信息打出的方法
	 * 
	 * @param errorCode
	 * @param errorMsg
	 * @return
	 */
	protected void buildResponse(String errorCode, String errorMsg, HttpServletResponse response) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(Constant.ERROR_CODE, errorCode);
		map.put(Constant.ERROR_MSG, errorMsg);
		logger.error("返回错误消息:" + errorMsg);
		String result = JSON.toJSONString(map);

		this.responseWrite(response, result);
	}

	protected Map<String, Object> responseMap(String code, String msg) {
		Map<String, Object> response = new HashMap<String, Object>();
		response.put(Constant.CODE, code);
		response.put(Constant.MSG, msg);
		return response;
	}

	/**
	 * 判断当前人员是否有该权限项的权限
	 * 
	 * @param permissionId
	 *            权限项的ID
	 * @return
	 */
	@SuppressWarnings({ "unchecked" })
	public boolean hasPermission(String permissionId) {
		String userId = (String) this.getSession().getAttribute(Constant.SYSTEM_LOGIN_USER_ID);
		if (Constant.ADMIN_ID.equals(userId)) {
			return true;
		}
		Map<String, String> permissionMap = (Map<String, String>) this.getSession()
				.getAttribute(Constant.PERSONAL_PERMISSION_MAP);
		return (permissionMap != null && permissionMap.containsKey(permissionId))
				? checkPermission(permissionMap.get(permissionId)) : false;
	}

	/**
	 * 检查当前用户是否拥有指定权限
	 * 
	 * @param method
	 *            权限对应的controller类名+方法名
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public boolean checkPermission(String method) {
		Set<String> personPermission = (Set<String>) this.getSession().getAttribute(Constant.PERSONAL_PERMISSION);
		Set<String> wholePermission = (Set<String>) getSession().getServletContext()
				.getAttribute(Constant.SOURCE_PERMISSION);
		if (wholePermission != null && wholePermission.contains(method)) {
			// 有权限控制的才验证
			return personPermission != null ? personPermission.contains(method) : false;
		} else {
			// 无权限控制的直接通过
			return true;
		}
	}
	/**
	 * 得到IP地址
	 * @param request
	 * @return
	 */
	public String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}
	
	public void putCommonPath(){
		int port = getRequest().getServerPort();
		String scheme = getRequest().getScheme();
		String path = getRequest().getScheme()+"://"+getRequest().getServerName() + ((("http".equals(scheme) && port == 80) ||("https".equals(scheme)  && port == 443)) ? "" : ":" + port) + getRequest().getContextPath();
		getSession().setAttribute("base",path);
		getSession().setAttribute("imgBase",path+"/images");
		getSession().setAttribute("imgPrePath",path+"/default/style/images");
		getSession().setAttribute("initImagePath",path+"/default");
	}
	
	protected String getBasePath(){
		int port = getRequest().getServerPort();
		String scheme = getRequest().getScheme();
		String path = getRequest().getScheme()+"://"+getRequest().getServerName() + ((("http".equals(scheme) && port == 80) ||("https".equals(scheme)  && port == 443)) ? "" : ":" + port) + getRequest().getContextPath();
		return path;
	}
	
	protected boolean isMobileDevice(){
		String qhd=getRequest().getHeader("user-agent");
		if(qhd!=null){
			if(qhd.indexOf("Android")>-1){
				return true;
			}else if(qhd.indexOf("iPhone")>-1){
				return true;
			}else if(qhd.indexOf("iPad")>-1){
				return true;
			}else if(qhd.indexOf("Windows")<0 && qhd.indexOf("Linux")<0 && qhd.indexOf("Apple") < 0){//根据请求的客户端信息判断 如果是非PC登录
				return true;
			}
		}
		return false;
	}
	
	protected String getCookieValue(String key){
		Cookie[] cookie = getRequest().getCookies();
		if(null==cookie || cookie.length==0) return null;
		for (int i = 0; i < cookie.length; i++) {
		Cookie cook = cookie[i];
		if(cook.getName().equalsIgnoreCase(key)){ //获取键 
			return cook.getValue().toString();
			}
		}
		return null;
	}
	
	/**
	 * 输出，同时清空outPutMsg
	 * @param response
	 * @param result
	 */

	public void outPrint(HttpServletResponse response, Object result) {
        try {
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.print(result.toString());
            getOutputMsg().clear();
        } catch (IOException e) {
        	logger.error("输出报错:", e);
        }
    }
	
	/**
	 * 获取验证错误详情
	 * @param errorList
	 * @return
	 */
	public Map<String, String> getValidErrors(List<FieldError> errorList){
		Map<String, String> errorMap = new LinkedHashMap<String, String>();
		for(FieldError error : errorList){
			errorMap.put(error.getField(), error.getDefaultMessage());
		}
		return errorMap;
	}
	
	/**
	 * 添加Flash消息
	 * @param message
	 */
	protected void addMessage(RedirectAttributes redirectAttributes, String... messages) {
		StringBuilder sb = new StringBuilder();
		for (String message : messages){
			sb.append(message).append(messages.length>1?"<br/>":"");
		}
		redirectAttributes.addFlashAttribute("message", sb.toString());
	}
	/**
	 * 参数绑定异常
	 */
	@ExceptionHandler({BindException.class, ValidationException.class})
    public String bindException() {  
        return "error/400";
    }
	
	/**
	 * 授权登录异常
	 */
	@ExceptionHandler({AuthenticationException.class})
    public String authenticationException() {  
        return "error/403";
    }
	
	/**
	 * 初始化数据绑定
	 * 1. 将所有传递进来的String进行HTML编码，防止XSS攻击
	 * 2. 将字段中Date类型转换为String类型
	 */
	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		// String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
		binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
			@Override
			public void setAsText(String text) {
				setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
			}
			@Override
			public String getAsText() {
				Object value = getValue();
				return value != null ? value.toString() : "";
			}
		});
		
		binder.registerCustomEditor(Date.class,new DateEditor());
	}
	
	/**
	 * 判断非管理   排除已删除数据
	 * @param request
	 * @return
	 
	public Map<String, Object> getParams(){
		Map<String, Object> params = new HashMap<String, Object>();	
		SysUser user = RedisWebUtils.getLoginUser();
		if(!user.isAdmin()){
			params.put(Constant.DELTE_FLAG, Constant.DELTE_FLAG_NO);
		}
		return params;
	}*/
}